package io.github.talelin.latticy.service.impl;

import com.qiniu.util.StringUtils;
import io.github.talelin.autoconfigure.exception.NotFoundException;
import io.github.talelin.latticy.service.ArticleService;
import io.github.talelin.latticy.vo.ArticleSummaryVO;
import io.github.talelin.latticy.vo.ArticleVO;
import io.github.talelin.latticy.vo.PageResponseVO;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 */
@Service
public class ArticleServiceImpl implements ArticleService {

    @Autowired
    private RestHighLevelClient highLevelClient;

    @Override
    public PageResponseVO<ArticleSummaryVO> searchES(String query, Integer from, Integer size) throws IOException {

        SearchRequest searchRequest = new SearchRequest("articles");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.matchQuery("content",query));
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("content");
        sourceBuilder.highlighter(highlightBuilder);
        sourceBuilder.from(from-1);
        sourceBuilder.size(size);
        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        SearchHit[] hits = searchResponse.getHits().getHits();
        Long total = searchResponse.getHits().getTotalHits().value;
        List<ArticleSummaryVO> articleSummaryVOList = new ArrayList<>();

        for (SearchHit hit : hits) {
            Map<String, Object> res = hit.getSourceAsMap();
            Map<String, HighlightField> highlightRes = hit.getHighlightFields();
            String summary = StringUtils.join(highlightRes.get("content").getFragments(), "\n");
            String title = (String) res.get("title");
            Integer id = (Integer) res.get("id") ;
            String create_time = (String) res.get("create_time");
            Integer char_sum = (Integer) res.get("char_sum");
            Integer similar_rate = (Integer) res.get("similar_rate");
            ArticleSummaryVO articleSummaryVO = ArticleSummaryVO.builder().
                    Title(title).
                    Summary(summary).
                    Id(id).
                    CreateTime(create_time).
                    CharSum(char_sum).
                    SimilarRate(similar_rate).
                    build();
            articleSummaryVOList.add(articleSummaryVO);
        }
        return new PageResponseVO<ArticleSummaryVO>(Math.toIntExact(total),articleSummaryVOList,from,size);
    }

    @Override
    public ArticleVO getArticle(Integer id) throws IOException {
        SearchRequest searchRequest = new SearchRequest("articles");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.matchQuery("id",id));
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        SearchHit[] hits = searchResponse.getHits().getHits();
        if(hits.length != 1){
            throw new NotFoundException(20001);
        }
        SearchHit hit = hits[0];
        Map<String, Object> article = hit.getSourceAsMap();
        return ArticleVO.builder().
                Id((Integer)article.get("id")).
                Title((String)article.get("title")).
                Content((String)article.get("content")).
                build();
    }
}
